﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using TFSTools.TFSLibrary;

namespace TFSTools.TestManagement.TestCaseReview
{
    [Serializable]
    public class ProjectSetting
    {
        public ProjectSetting() 
        {
            ShowCommentWarning = true;
        }

        public string ConnectionDescription { get; set; }

        public string StepCommentFieldReferenceName { get; set; }

        public bool ShowCommentWarning { get; set; }
    }

    public class ProjectSettingList : List<ProjectSetting>
    {
        public ProjectSettingList()
        {

        }

        public ProjectSettingList(IEnumerable<ProjectSetting> collection)
            : base(collection)
        {

        }
    }

    public class ProjectSettings : Dictionary<string, ProjectSetting>
    {
        public ProjectSetting this[TFSConnection connection]
        {
            get
            {
                var connectionDescription = this.TFSConnectionDescription(connection);
                CheckForSettings(connection);
                return this[connectionDescription];
            }
        }

        public void CheckForSettings(TFSConnection connection)
        {
            var connectionDescription = this.TFSConnectionDescription(connection);

            if (!this.ContainsKey(connectionDescription))
            {
                var newProjectSetting = new ProjectSetting();
                newProjectSetting.ConnectionDescription = connectionDescription;
                newProjectSetting.StepCommentFieldReferenceName = Properties.Settings.Default.DefaultStepCommentFieldReferenceName;
                this.Add(newProjectSetting.ConnectionDescription, newProjectSetting);
                this.SaveToSettings();
            }
        }

        public void SaveToSettings(TFSConnection connection, string stepCommentFieldReferenceName, bool? showStepCommentWarning)
        {
            var connectionDescription = this.TFSConnectionDescription(connection);

            if (!this.ContainsKey(connectionDescription))
            {
                var newProjectSetting = new ProjectSetting();
                newProjectSetting.ConnectionDescription = connectionDescription;
                this.Add(newProjectSetting.ConnectionDescription, newProjectSetting);
            }

            if (!string.IsNullOrEmpty(stepCommentFieldReferenceName))
            {
                this[connectionDescription].StepCommentFieldReferenceName = stepCommentFieldReferenceName;
            }

            if (showStepCommentWarning != null)
            {
                this[connectionDescription].ShowCommentWarning = showStepCommentWarning == true;
            }

            this.SaveToSettings();
        }

        private void SaveToSettings()
        {
            // Convert this Dictionary<> into a List<> for serialization
            // List<> will be converted back into a Dictionary<> upon deserialization
            var projectSettingList = new ProjectSettingList(from kvp in this select kvp.Value);

            XmlSerializer serializer = new XmlSerializer(projectSettingList.GetType());

            using (StringWriter writer = new StringWriter())
            {
                serializer.Serialize(writer, projectSettingList);

                Properties.Settings.Default.StepCommentFieldReferenceNames = writer.ToString();
                Properties.Settings.Default.Save();
            }
        }

        public static ProjectSettings GetFromSettings()
        {
            string xmlString = Properties.Settings.Default.StepCommentFieldReferenceNames;
            var projectSettingList = Deserialize(xmlString);
            var result = new ProjectSettings();
            
            if (projectSettingList != null && projectSettingList.Any())
            {
                projectSettingList.ForEach(projectSetting => result.Add(projectSetting.ConnectionDescription, projectSetting));
            }

            return result;
        }

        private static ProjectSettingList Deserialize(string xmlString)
        {
            ProjectSettingList result = null;
            StringReader reader = null;

            try
            {
                XmlSerializer serializer = new XmlSerializer(typeof(ProjectSettingList));

                using (reader = new StringReader(xmlString))
                {
                    var attemptedResult = (ProjectSettingList)serializer.Deserialize(reader);
                    result = attemptedResult;
                }

                reader = null;
            }
            catch
            {
            }
            finally
            {
                if (reader != null)
                {
                    reader.Close();
                }
            }

            return result;
        }

        private string TFSConnectionDescription(TFSConnection connection)
        {
            return connection.ServerName + "; " + connection.SelectedProject.Name;
        }
    }
}
